/*
 * @Description:
 * @Author: dh
 * @Date: 2021-08-19 17:18:39
 * @LastEditors: dh
 * @LastEditTime: 2025-09-10 16:56:58
 */
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'

/* 简单版，功能缺失 */
class myPromise1 {
	constructor(executor) {
		this.value = void 0
		this.reason = void 0
		this.status = 'PENDING'
		this.resolveFns = []
		this.rejectFns = []

		const resolve = value => {
			if (this.status !== 'PENDING') return
			this.status = 'RESOLVED'
			this.value = value
			this.resolveFns.forEach(fn => fn())
		}

		const reject = e => {
			if (this.status !== 'PENDING') return
			this.status = 'REJECTED'
			this.reason = e
			this.rejectFns.forEach(fn => fn())
		}

		try {
			executor(resolve, reject)
		} catch (err) {
			reject(err)
		}
	}

	then(successFn) {
		if (this.status === 'RESOLVED') {
			successFn(this.value)
		}
		if (this.status === 'PENDING') {
			// 推进队列中，resolved 后统一执行
			this.resolveFns.push(() => successFn(this.value))
		}
	}

	catch(errFn) {
		if (this.status === 'REJECTED') {
			const result = errFn(this.reason)
		}
		if (this.status === 'PENDING') {
			this.rejectFns.push(() => errFn(this.reason))
		}
	}
}

class MyPromise {
	#state = PENDING
	#value = undefined
	#setState(state, value) {
		this.#state = state
		this.#value = value
		this.#runTask()
	}
	#runTask() {
		runMicrotask(() => {
			if (this.#state === FULFILLED) {
				this.onFulfilledCallbacks.forEach(fn => fn())
				this.onFulfilledCallbacks = []
			} else if (this.#state === REJECTED) {
				this.onRejectedCallbacks.forEach(fn => fn())
				this.onRejectedCallbacks = []
			}
		})
	}

	constructor(executor) {
		this.onFulfilledCallbacks = []
		this.onRejectedCallbacks = []

		// TODO
		// 如果 x 是 Promise 实例本身，则抛出错误
		// 如果 x 是一个 Promise 对象，那么 then 函数的执行取决这个 x 的状态，如果 x 也调用 resolve(y),其中 y 也是一个 promise 对象.那么 then 函数的执行取决于这个 promise 对象，依次类推，直到最后一个 promise 状态更改
		// 如果 x 是一个 thenable 对象，就是一个对象包含 then 这个属性，或者是一个函数包含一个 then 的静态方法,那么直接执行 then 函数,并返回
		// 如果 x 是一个普通值，直接变成 onFulfilled 状态，执行后面的 then 函数
		const resolve = value => {
			if (this === value) {
				return reject(new TypeError('Chaining cycle detected for promise'))
			}
			if (typeof value === 'object' && typeof value.then === 'function') {
				return value.then(resolve, reject)
			}
			if (value instanceof MyPromise) {
				return value.then(resolve, reject)
			}

			if (this.#state !== PENDING) return
			this.#setState(FULFILLED, value)
		}

		const reject = reason => {
			if (this.#state !== PENDING) return
			this.#setState(REJECTED, reason)
		}

		try {
			executor(resolve, reject)
		} catch (error) {
			this.reject(error)
		}
	}

	// TODO 核心方法
	then(onFulfilled, onRejected) {
		onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value
		onRejected =
			typeof onRejected === 'function'
				? onRejected
				: value => {
						throw value
				  }

		const promise2 = new MyPromise((resolve, reject) => {
			this.onFulfilledCallbacks.push(() => {
				try {
					const res = onFulfilled(this.#value)
					resolvePromise(promise2, res, resolve, reject)
				} catch (error) {
					reject(error)
				}
			})
			this.onRejectedCallbacks.push(() => {
				try {
					const res = onRejected(this.#value)
					resolvePromise(promise2, res, resolve, reject)
				} catch (error) {
					reject(error)
				}
			})
			this.#runTask()
		})
		return promise2
	}

	catch(onRejected) {
		return this.then(null, onRejected)
	}

	finally(onFinally) {
		return this.then(
			value => {
				onFinally()
				return value
			},
			reason => {
				onFinally()
				throw reason
			}
		)
	}
}

// 模拟微任务
function runMicrotask(fn) {
	if (typeof queueMicrotask === 'function') {
		queueMicrotask(fn)
	} else if (process && process.nextTick) {
		process.nextTick(fn)
	} else if (typeof MutationObserver === 'function') {
		const observer = new MutationObserver(fn)
		const textNode = document.createTextNode(String(Math.random()))
		observer.observe(textNode, {
			characterData: true,
		})
		textNode.data = String(Math.random())
	} else {
		setTimeout(fn, 0)
	}
}

// 判断promise/A+规范
function resolvePromise(promise2, x, resolve, reject) {
	if (promise2 === x) {
		return reject(new TypeError('Chaining cycle detected for promise'))
	}
	if (typeof x === 'object' && typeof x.then === 'function') {
		// return new MyPromise((resolve, reject) => {
		x.then(resolve, reject)
		// })
	}
	if (x instanceof MyPromise) {
		x.then(resolve, reject)
	} else {
		resolve(x)
	}
}

// 测试
let p = new MyPromise((resolve, reject) => {
	let obj = {
		then: cb => {
			setTimeout(() => {
				cb(1111)
			}, 3000)
		},
	}
	resolve(obj)
	// reject(3)

	// setTimeout(() => {
	// 	reject(1)
	// }, 1000)
})

p.then(
	res => {
		console.log('success', res)
		return new MyPromise((resolve, reject) => {
			setTimeout(() => {
				resolve(2)
			}, 2000)
		})
	},
	err => {
		console.log('err', err)
	}
)

	.finally(() => {
		console.log('finally')
	})
	.catch(err => {
		console.log('catch', err)
	}).then((res)=>{
		console.log('success2', res)
})

console.log('end')
